﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.Xml;
using System.IO;
using System.Diagnostics;

using XEvents.Library;
using WeifenLuo.WinFormsUI.Docking;


namespace ExtendedEventsManager
{
    public partial class SessionEditorForm : DockContent
    {
        #region Private Members
        private bool _prebinding;
        private bool _newSession = true;
        private EventSession _session;
        BindingSource bsEvents;
        BindingSource bsTargets;
        BindingSource bsOptions;

        #endregion

        #region Constructors

        public SessionEditorForm(EventSession session, bool newsession)
        {
            InitializeComponent();
            InitializePrivateVariables();
            dgv_Targets.AutoGenerateColumns = false;
            dgv_Events.AutoGenerateColumns = false;
            _newSession = newsession;
            _session = session;
            _prebinding = true;
            BindOptionsPage();
            BindSessionToForm();
            _prebinding = false;
        }

        #endregion

        #region Properties

        public string SessionName
        {
            get { return txt_SessionName.Text; }
        }
        
        public EventSession Session
        {
            get { return _session; }
        }

        public BindingSource EventBindingSource
        {
            get { return bsEvents; }
        }

        public BindingSource TargetBindingSource
        {
            get { return bsTargets; }
        }
        #endregion

        #region Form Methods

        private void InitializePrivateVariables()
        {
            bsEvents = new BindingSource();
            bsTargets = new BindingSource();
            bsOptions = new BindingSource();
        }

        private void BindSessionToForm()
        {
            txt_SessionName.Text = _session.Name;
            bsEvents.DataSource = _session.Events;
            dgv_Events.DataSource = bsEvents;
            bsTargets.DataSource = _session.Targets;
            dgv_Targets.DataSource = bsTargets;
        }

        private void BindOptionsPage()
        {
            cmbx_EventRetentionMode.DataSource = Enum.GetNames(typeof(EventRetentionMode));
            cmbx_EventRetentionMode.SelectedItem = Session.EventRetentionMode.ToString();

            cmbx_MemoryPartitionMode.DataSource = Enum.GetNames(typeof(MemoryPartitionMode));
            cmbx_MemoryPartitionMode.SelectedItem = Session.MemoryPartitionMode.ToString();

            cmbx_StartupState.DataSource = Enum.GetNames(typeof(StartupState));
            cmbx_StartupState.SelectedItem = Session.StartupState.ToString();

            cmbx_TrackCausality.DataSource = Enum.GetNames(typeof(TrackCausality));
            cmbx_TrackCausality.SelectedItem = Session.TrackCausality.ToString();

            nUD_MaxDispatchLatency.Value = Convert.ToDecimal(Session.MaxDispatchLatency);
            nUD_MaxEventSize.Value = Convert.ToDecimal(Session.MaxEventSize);
            nUD_MaxMemory.Value = Convert.ToDecimal(Session.MaxMemory);
        }

        private string GetScript()
        {
            string script = string.Empty;

            try
            {
                _session.GenerateSQLScript();
            }
            catch (Exception ex)
            {
                MessageBox.Show("An error occured scripting the EventSession.\r\n\r\nThe message returned was:\r\n\r\n" + ex.Message, "Scripting Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            return script;
        }

        #endregion

        #region Form Events

        #region Buttons
        private void btn_Script_Click(object sender, EventArgs e)
        {
            ToolStripMenuItem mi = (ToolStripMenuItem)sender;
            MainForm mf = (MainForm)this.DockPanel.Parent;

            string script = GetScript();

            if (!(script == string.Empty))
            {

                switch (mi.Text)
                {
                    case "To Message Box":
                        MessageBox.Show(script);
                        break;
                    case "To File":
                        mf.WriteTextToFile(script);
                        break;
                    case "To Clipboard":
                        mf.CopyToClipboard(script);
                        break;
                    case "To New SSMS Window":
                        mf.OpenWithSSMS(script);
                        break;
                }
            }
        }

        private void ll_AddTarget_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            AddTargetToSessionForm at = new AddTargetToSessionForm(this);
            at.ShowDialog();
            bsTargets.ResetBindings(true);
        }

        private void ll_AddEvent_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            AddEventToSessionForm ae = new AddEventToSessionForm(this);
            ae.ShowDialog();
            bsEvents.ResetBindings(true);
        }

        private MainForm MainForm
        {
            get { return (MainForm)this.DockPanel.Parent; }
        }

        private void btn_Ok_Click(object sender, EventArgs e)
        {

            if (_session.SessionState == SessionState.Start && _session.RequiresDrop && MainForm.s.DropActiveWarning)
            {
                DialogResult dr = MessageBox.Show("The changes made require that the Event Session be dropped and then recreated.\r\n\r\nAre you sure you want to drop the " + this._session.Name + " session?\r\n\r\nThe current Session State is " + this._session.SessionState.ToString() + ".", "Drop Session Confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                if (dr == DialogResult.No)
                {
                    return;
                }
            }

            try
            {
                _session.Update();
                this.Close();
            }
            catch (Exception ex)
            {
                if (ex is ArgumentException)
                {
                    MessageBox.Show("An error occured scripting the EventSession.\r\n\r\nThe message returned was:\r\n\r\n" + ex.Message, "Scripting Error!", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                else
                {

                    string linedscript = string.Empty;
                    string[] str_arr = (_session.GenerateSQLScript().Replace("\r\n", "|").Split('|'));

                    int i = 1;
                    foreach (string str in str_arr)
                    {
                        linedscript += i.ToString() + ":".PadRight(5 - str_arr.Length.ToString().Length, ' ') + str + "\r\n";
                        i++;
                    }
                    System.Data.SqlClient.SqlException se = (System.Data.SqlClient.SqlException)ex.InnerException;
                    string errors = string.Empty;
                    if (se.Errors.Count > 0)
                    {
                        foreach (System.Data.SqlClient.SqlError sqlerr in se.Errors)
                        {
                            errors += "Msg " + sqlerr.Number.ToString() + ", Level " + sqlerr.Class.ToString() + ", State " + sqlerr.State.ToString() + ", Line " + sqlerr.LineNumber.ToString() + "\r\n" + sqlerr.Message + "\r\n\r\n";
                        }
                    }
                    DialogResult dr = MessageBox.Show(@"An Exception Occured Trying to save this Event Session:\r\n
To view the errors that occured click 'Yes',
or to review the Event Session click 'No'.

When reviewing the Event Session check the following
common mistakes.

1.  Ensure that all predicates have an operator and value to evaluate.
2.  Ensure that any target option is set to a valid value for the target.
", "DDL Syntax Error", MessageBoxButtons.YesNo, MessageBoxIcon.Error);
                    switch (dr)
                    {
                        case DialogResult.Yes:
                            MessageBox.Show(linedscript + "\r\n\r\n\r\n" + errors, "Error Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
                            break;
                        case DialogResult.No:
                            break;
                    }
                }
            }
        }

        private void btn_Cancel_Click(object sender, EventArgs e)
        {
            this.DialogResult = DialogResult.Cancel;
            this.Close();
        }

        private void toolStripSplitButton_Script_ButtonClick(object sender, EventArgs e)
        {
            string script = GetScript();

            if (!(script == string.Empty))
            {
                ((MainForm)this.DockPanel.Parent).OpenWithSSMS(script);
            }
        }

        #endregion

        #region GridViews
        private void dgv_Events_CellValueChanged(object sender, DataGridViewCellEventArgs e)
        {

        }

        private void dgv_Events_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.ColumnIndex > -1 && e.RowIndex > -1 && this._session.Events != null)
            {
                if (dgv_Events.Columns[e.ColumnIndex].Name == "dgvEvents_Edit")
                {
                    EventSessionEvent evt = (EventSessionEvent)bsEvents[e.RowIndex];
                    if (!(evt.Name == string.Empty && evt.ActionString == string.Empty && evt.Predicate == string.Empty))
                    {
                        AddEventToSessionForm sf = new AddEventToSessionForm(this, evt);
                        DialogResult dr = sf.ShowDialog();
                        if (dr == DialogResult.OK)
                        {
                            bsEvents.Remove(evt);
                            bsEvents.ResetBindings(true);
                        }
                    }
                }
                else if (dgv_Events.Columns[e.ColumnIndex].Name == "dgvEvents_Delete")
                {
                    bsEvents.RemoveAt(e.RowIndex);
                }
            }
        }

        private void dgv_Targets_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.ColumnIndex > -1 && e.RowIndex > -1)
            {
                if (dgv_Targets.Columns[e.ColumnIndex].Name == "dgvTargets_Edit")
                {
                    EventSessionTarget tgt = (EventSessionTarget)bsTargets[e.RowIndex];

                    if (!(tgt.Name == string.Empty && tgt.Options.Count == 0))
                    {
                        AddTargetToSessionForm sf = new AddTargetToSessionForm(this, tgt);
                        DialogResult dr = sf.ShowDialog();
                        if (dr == DialogResult.OK)
                        {
                            bsTargets.Remove(tgt);
                            bsTargets.ResetBindings(true);
                        }
                    }
                }
                else if (dgv_Targets.Columns[e.ColumnIndex].Name == "dgvTargets_Delete")
                {
                    bsTargets.RemoveAt(e.RowIndex);
                }
            }
        }

        #endregion

        private void txt_SessionName_TextChanged(object sender, EventArgs e)
        {
            this.Text = "Session Editor (" + txt_SessionName.Text + ")";
            _session.Name = txt_SessionName.Text;
        }

        private void SessionEditorForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            ((MainForm)this.DockPanel.Parent).ServerExplorer.ReloadNode(this._session.SqlServer.ServerName, this.SessionName);
        }

        private void tv_Menu_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if (e.Node.Name == "tvMenu_Options")
            {
                this.grpbx_Options.BringToFront();
            }
            else if (e.Node.Name == "tvMenu_Definition")
            {
                this.grpbx_Definition.BringToFront();
            }
        }

        private void cmbx_EventRetentionMode_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (!_prebinding)
                Session.EventRetentionMode = (EventRetentionMode)Enum.Parse(typeof(EventRetentionMode), cmbx_EventRetentionMode.SelectedItem.ToString());
        }

        private void nUD_MaxDispatchLatency_ValueChanged(object sender, EventArgs e)
        {
            if (!_prebinding)
                Session.MaxDispatchLatency = Convert.ToInt32(nUD_MaxDispatchLatency.Value);
        }

        private void nUD_MaxEventSize_ValueChanged(object sender, EventArgs e)
        {
            if (!_prebinding)
                Session.MaxEventSize = Convert.ToInt32(nUD_MaxEventSize.Value);
        }

        private void nUD_MaxMemory_ValueChanged(object sender, EventArgs e)
        {
            if (!_prebinding)
                Session.MaxMemory = Convert.ToInt32(nUD_MaxMemory.Value);
        }
 
        private void cmbx_MemoryPartitionMode_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (!_prebinding)
                Session.MemoryPartitionMode = (MemoryPartitionMode)Enum.Parse(typeof(MemoryPartitionMode), cmbx_MemoryPartitionMode.SelectedItem.ToString());
        }

        private void cmbx_TrackCausality_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (!_prebinding)
                Session.TrackCausality = (TrackCausality)Enum.Parse(typeof(TrackCausality), cmbx_TrackCausality.SelectedItem.ToString());
        }

        private void cmbx_StartupState_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (!_prebinding)
                Session.StartupState = (StartupState)Enum.Parse(typeof(StartupState), cmbx_StartupState.SelectedItem.ToString());
        }
        #endregion

    }
}
